#include "nmfield.h"
#include "util.h"
#include "rectype.h"
#include <memory.h>

using namespace std;
using namespace opsrc::stdf;

template <typename T,int L>
NmField<T,L>::NmField() {
}

template <typename T, int L>
NmField<T,L>::NmField(char *buf, endian e):en(e) {
	decode(buf);
}

template <typename T, int L>
NmField<T,L>::~NmField() {
}

template <typename T, int L>
T NmField<T,L>::decode(char* buf) {
	// If little endian, swap byte order
	// where least significant byte is at lower address 
	// For big endian, the most significant byte is at the lower address
	
	char tmp[L];
	::memcpy(tmp, buf, L);
	if (en == little_endian) {
        Util::swapByteChar(&tmp[0], L);
	}
    data = Util::charToUnsignInt(&tmp[0], L);
    
    // add in length
    len = L;

	return data;
}

template <typename T, int L>
int NmField<T,L>::getByteCount() const {
    return len;	
}

template <typename T, int L>
T NmField<T,L>::getData() const {
  return data;	
}


template <typename T, int L>
int NmField<T,L>::getTotalByteCount()  const {
   return len;	
}

// **************************************************
// Specialization for short datatype
// **************************************************
template <int L>
NmField<short,L>::NmField() {
}

template <int L>
NmField<short,L>::NmField(char *buf, endian e):en(e) {
	decode(buf);
}

template <int L>
NmField<short,L>::~NmField() {
}


template <int L>
short NmField<short,L>::decode(char* buf) {
	// If little endian, swap byte order
	// where least significant byte is at lower address 
	// For big endian, the most significant byte is at the lower address
	
	char tmp[L];
	::memcpy(tmp, buf, L);
	if (en == little_endian) {
        Util::swapByteChar(&tmp[0], L);
	}
    data = Util::convertCharToShort(&tmp[0], L);
    
    // add in length
    len = L;

	return data;
}

template <int L>
int NmField<short,L>::getByteCount() const {
    return len;	
}

template <int L>
short NmField<short,L>::getData() const {
  return data;	
}


template <int L>
int NmField<short,L>::getTotalByteCount()  const {
   return len;	
}


// **************************************************
// Specialization for float datatype
// **************************************************
template <int L>
NmField<float,L>::NmField() {
}

template <int L>
NmField<float,L>::NmField(char *buf, endian e):en(e) {
	decode(buf);
}

template <int L>
NmField<float,L>::~NmField() {
}


template <int L>
float NmField<float,L>::decode(char* buf) {
	// If little endian, swap byte order
	// where least significant byte is at lower address 
	// For big endian, the most significant byte is at the lower address
	
	char tmp[L];
	::memcpy(tmp, buf, L);
	if (en == little_endian) {
        Util::swapByteChar(&tmp[0], L);
	}
    data = Util::charToFloat(&tmp[0], L);
    
    // add in length
    len = L;

	return data;
}

template <int L>
int NmField<float,L>::getByteCount() const {
    return len;	
}

template <int L>
float NmField<float,L>::getData() const {
  return data;	
}


template <int L>
int NmField<float,L>::getTotalByteCount()  const {
   return len;	
}


// **************************************************
// Specialization for double datatype
// **************************************************
template <int L>
NmField<double,L>::NmField() {
}

template <int L>
NmField<double,L>::NmField(char *buf, endian e):en(e) {
	decode(buf);
}

template <int L>
NmField<double,L>::~NmField() {
}


template <int L>
double NmField<double,L>::decode(char* buf) {
	// If little endian, swap byte order
	// where least significant byte is at lower address 
	// For big endian, the most significant byte is at the lower address
	
	char tmp[L];
	::memcpy(tmp, buf, L);
	if (en == little_endian) {
        Util::swapByteChar(&tmp[0], L);
	}
    data = Util::charToDouble(&tmp[0], L);
    
    // add in length
    len = L;

	return data;
}

template <int L>
int NmField<double,L>::getByteCount() const {
    return len;	
}

template <int L>
double NmField<double,L>::getData() const {
  return data;	
}


template <int L>
int NmField<double,L>::getTotalByteCount()  const {
   return len;	
}

